/**********************************Copyright (c)**********************************
**                       STM32F103 串口4驱动
**
**                             源文件
**
*********************************************************************************/
/**
 * @file    usart4.c
 * @author  User
 * @version v1.0.0
 * @date    2025.10.15
 * @brief   UART4驱动实现 - 用于涂鸦WiFi模块串口通信
 *          引脚: PC10(TX), PC11(RX)
 *          波特率: 9600 (涂鸦协议要求)
 */

#include "usart4.h"
#include "wifi.h"  // 包含涂鸦协议头文件
/*
    开发板上使用的是串口4 在样板上用的串口1
*/
/**
 * @brief  串口1初始化
 * @param  bound: 波特率 (涂鸦协议要求9600)
 * @return 无
 * @note   引脚: PA9(TX), PA10(RX)
 *         配置: 8数据位, 1停止位, 无校验, 无流控
 */
void USART1_Init(u32 bound)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* ========== 1. 使能时钟 ========== */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);  // USART1时钟 (APB2)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  // GPIOA时钟

    /* ========== 2. 配置GPIO引脚 ========== */

    // PA9: USART1_TX (复用推挽输出)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        // 复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // PA10: USART1_RX (浮空输入)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  // 浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* ========== 3. 配置USART1参数 ========== */
    USART_InitStructure.USART_BaudRate = bound;                                     // 波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;                    // 8数据位
    USART_InitStructure.USART_StopBits = USART_StopBits_1;                         // 1停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;                            // 无校验
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无流控
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                // 收发模式
    USART_Init(USART1, &USART_InitStructure);

    /* ========== 4. 配置NVIC中断 ========== */
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  // 抢占优先级2
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;         // 子优先级2
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* ========== 5. 使能接收中断 ========== */
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  // 使能接收中断

    /* ========== 6. 使能USART1 ========== */
    USART_Cmd(USART1, ENABLE);
}


/**
 * @brief  串口1发送单字节
 * @param  data: 要发送的字节
 * @return 无
 * @note   供涂鸦协议的uart_transmit_output()调用
 *         该函数会阻塞等待发送完成
 */
void USART1_SendByte(u8 data)
{
    /* 等待发送寄存器空 */
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

    /* 发送数据 */
    USART_SendData(USART1, data);

    /* 等待发送完成 */
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}


/**
 * @brief  串口1发送字符串
 * @param  str: 字符串指针
 * @return 无
 * @note   用于调试输出，发送以'\0'结尾的字符串
 */
void USART1_SendString(char *str)
{
    if(str == NULL) {
        return;
    }

    while(*str)
    {
        USART1_SendByte(*str++);
    }
}

/**
 * @brief  串口1发送数据块
 * @param  buf: 数据缓冲区指针
 * @param  len: 数据长度
 * @return 无
 */
void USART1_SendData(u8 *buf, u16 len)
{
    u16 i;

    if(buf == NULL || len == 0) {
        return;
    }

    for(i = 0; i < len; i++)
    {
        USART1_SendByte(buf[i]);
    }
}

/**
 * @brief  USART1中断服务函数
 * @param  无
 * @return 无
 * @note   接收到的数据会传递给涂鸦协议处理函数uart_receive_input()
 *         该函数可以在此处实现，也可以在stm32f10x_it.c中实现
 */
void USART1_IRQHandler(void)
{
    u8 res;

    // 接收中断
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        // 读取接收到的数据
        res = USART_ReceiveData(USART1);

        // 将数据传递给涂鸦协议处理
        uart_receive_input(res);
    }
}
